package com.xx.cloud.pay.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.xx.cloud.pay.config.pay.MyPayConfig;
import com.xx.cloud.pay.entity.CreateOrderEntity;
import com.xx.cloud.pay.entity.WxPayConf;
import com.xx.cloud.pay.mapper.WxPayConfMapper;
import com.xx.cloud.pay.result.R;
import com.xx.cloud.pay.service.PayUnifyService;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static com.xx.cloud.pay.result.ImagesUtils.imageToBase64;


@Service
public class PayUnifyServiceImpl implements PayUnifyService {

    @Autowired
    private WxPayConfMapper wxPayConfMapper;

    @Override
    public R createOrder(CreateOrderEntity createOrderEntity) throws WxPayException {

        String id = createOrderEntity.getId();

        WxPayConf wxPayConf = wxPayConfMapper.selectById(id);
        if(ObjectUtils.isEmpty(wxPayConf)){
            return R.failed("租户不存在！");
        }


        // TODO 10 就是0.1  -》100 -》就是1 封装金额、
        WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
        amount.setCurrency("CNY");
        amount.setTotal(1);  //金额

        //封装OpenId
        WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
        request.setPayer(payer.setOpenid(createOrderEntity.getOpenid()));

        request.setAmount(amount); //金额对象
        request.setDescription("DNF");

        String nextIdStr = IdUtil.getSnowflakeNextIdStr();
        //TODO 商户订单号
        request.setOutTradeNo(nextIdStr);

        request.setNotifyUrl(wxPayConf.getNotifyUrl());
        //封装返回下单参数
        WxPayUnifiedOrderV3Result.JsapiResult orderV3 = null;


        //TODO 1、小程序/公众号
        if (TradeTypeEnum.JSAPI.toString().equals(wxPayConf.getTradeType())) {
            //TODO 调用下单接口
            orderV3 = MyPayConfig.WxPayService(wxPayConf).createOrderV3(TradeTypeEnum.JSAPI, request);
        }

        //TODO 2、网站网页支付
        if (TradeTypeEnum.NATIVE.equals(wxPayConf.getTradeType())) {
            //TODO 1、支付方式
            String order = MyPayConfig.WxPayService(wxPayConf).createOrderV3(TradeTypeEnum.NATIVE, request);

            //保存到数据库
            String result = imageToBase64(QrCodeUtil.generate(order, 300, 300));

            //订单号
            orderV3.setNonceStr(nextIdStr);

            //二维码
            orderV3.setPackageValue(result);

        }

        //TODO 3、H5支付
        if (TradeTypeEnum.H5.equals(wxPayConf.getTradeType())) {
            orderV3 = MyPayConfig.WxPayService(wxPayConf).createOrderV3(TradeTypeEnum.H5, request);
        }

        //TODO 4、APP支付
        if (TradeTypeEnum.APP.equals(wxPayConf.getTradeType())) {
            orderV3 = MyPayConfig.WxPayService(wxPayConf).createOrderV3(TradeTypeEnum.APP, request);
        }

        System.out.println(orderV3);

        return R.ok(orderV3, "下单成功！");

    }


    /**
     * 判断支付的逻辑
     * @param notifyData
     * @param request
     * @return
     */
    @Override
    public String parseOrderNotifyResultPersonV3(String notifyData, HttpServletRequest request) {
        SignatureHeader requestHeader = getRequestHeader(request);

        System.out.println(notifyData + "..." + requestHeader);
        //自己的业务罗
        // 更新订单状态 待支付、 更新已支付 更新时间   金额
        return "";
    }

    @Override
    public R refundV33(WxPayRefundV3Request request) {
        try {

            String id = "租户id";
            WxPayConf wxPayConf = wxPayConfMapper.selectById(id);

            WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
            amount.setTotal(request.getAmount().getTotal()); //总金额
            amount.setRefund(request.getAmount().getRefund()); //退款金额
            amount.setCurrency("CNY");
            //设置总金额
            request.setAmount(amount);

            //设置退款金额
            request.setOutRefundNo(request.getOutRefundNo());
            request.setOutTradeNo(request.getOutTradeNo());

            WxPayRefundV3Result wxPayRefundV3Result = MyPayConfig.WxPayService(wxPayConf).refundV3(request);
            System.out.println(wxPayRefundV3Result);
            return R.ok(wxPayRefundV3Result,"退款完成");
        } catch (WxPayException e) {

            return R.failed(e.getCustomErrorMsg());
        }
    }

    /**
     * 定时任务  20分钟会关掉  当前的时间减去  取出下单的时间   =  关单时间 （这个毫秒数大于20分钟就关掉）
     * @param request
     * @return
     */
    @Override
    public R<?> closeOrderV33(WxPayUnifiedOrderV3Request request) {
        //TODO 1、调用查询订单 queryOrder(String transactionId, String outTradeNo)
        try {

            String id = "租户id";
            WxPayConf wxPayConf = wxPayConfMapper.selectById(id);

            //TODO 2、关单
            Object orderV3 = MyPayConfig.WxPayService(wxPayConf).createOrderV3(TradeTypeEnum.JSAPI, request);

            return R.ok();
        } catch (WxPayException e) {
            return R.failed(e.getReturnMsg());
        }

    }

    /**
     * 获取回调请求头：签名相关
     *
     * @param request HttpServletRequest
     * @return SignatureHeader
     */
    public SignatureHeader getRequestHeader(HttpServletRequest request) {
        // 获取通知签名
        String signature = request.getHeader("wechatpay-signature");
        String nonce = request.getHeader("wechatpay-nonce");
        String serial = request.getHeader("wechatpay-serial");
        String timestamp = request.getHeader("wechatpay-timestamp");

        SignatureHeader signatureHeader = new SignatureHeader();
        signatureHeader.setSignature(signature);
        signatureHeader.setNonce(nonce);
        signatureHeader.setSerial(serial);
        signatureHeader.setTimeStamp(timestamp);
        return signatureHeader;
    }
}
